﻿using System.Collections.Generic;
using System.Linq;
using DataAssociations.AssociationMiningAlgorithms.FpTree;
using DataAssociations.AssociationMiningAlgorithms.Apriori;
using System;

namespace DataAssociations.AssociationMiningAlgorithms
{
    internal class Program
    {
        private static void AddResultLine(string text)
        {
            Console.WriteLine(text);
        }

        private static void Main()
        {
            #region #fptree test app
            var sets = new List<List<string>>
                           {
                               new List<string> {"a", "b", "c", "d", "e"},
                               new List<string> {"a", "b", "c"},
                               new List<string> {"a", "c", "d", "e"},
                               new List<string> {"b", "c", "d", "e"},
                               new List<string> {"b", "c"},
                               new List<string> {"b", "d", "e"},
                               new List<string> {"c", "d", "e"},
                           };
            var knownElements = sets.SelectMany(x => x.Select(y => y)).Distinct();
            var occurances = knownElements.ToDictionary(knownElement => knownElement, knownElement => 0);
            foreach (var set in sets)
            {
                foreach (var element in set)
                {
                    occurances[element]++;
                }
            }
            var sortedOccurances =
                (from entry in occurances
                 orderby entry.Value
                     descending
                 select entry.Key).ToList();

            for (var i = 0; i < sets.Count; i++)
            {
                sets[i] = sets[i].OrderBy(x => x, new CustomComparer(occurances)).ToList();
            }
            var fpgTree = new FPGTree(sets);
            var hashedPaths = fpgTree.BuildHashedPathsToEachLeaf();
            var conditionalPatternsBuilder = new ConditionalBaseBuilder(fpgTree, sortedOccurances, 1);
            var generatedFrequentPatterns = conditionalPatternsBuilder.Generate(hashedPaths);
            #endregion

            #region Apriori test app
            Itemset _items;
            ItemsetCollection _db;

            #region Set sample data
            //sample items
            _items = new Itemset();
            _items.Add(1);
            _items.Add(2);
            _items.Add(3);
            _items.Add(4);
            _items.Add(5);
            _items.Add(6);
            _items.Add(7);
            _items.Add(8);
            Console.WriteLine("Itemset used for DB generation: {0}", string.Join(",", _items.ToArray()));

            //sample database -this data will come from database in the real system
            _db = new ItemsetCollection();
            //_db.Add(new Itemset() { _items[0], _items[1], _items[2], _items[3], _items[4] });
            //_db.Add(new Itemset() { _items[1], _items[2] });
            //_db.Add(new Itemset() { _items[0], _items[1], _items[5] });
            //_db.Add(new Itemset() { _items[1], _items[0], _items[6] });
            //_db.Add(new Itemset() { _items[0], _items[5], _items[7] });
            _db.Add(new Itemset() { _items[0], _items[2], _items[3] });
            _db.Add(new Itemset() { _items[1], _items[2], _items[4] });
            _db.Add(new Itemset() { _items[0], _items[1], _items[2], _items[4] });
            _db.Add(new Itemset() { _items[2], _items[4] });

            Console.WriteLine("Database is the following: {0}", _db.ToString());

            #endregion

            var supportTreshHold = 50.00;
            var ConfidenceThreshold = 80.00;

            //get items
            Itemset uniqueItems = _db.GetUniqueItems();
            AddResultLine("Items: " + uniqueItems);
            AddResultLine(string.Empty);

            //do apriori
            ItemsetCollection L = Mining.DoApriori(_db, supportTreshHold);
            AddResultLine(L.Count + " Large Itemsets after Apriori analisys");
            foreach (Itemset itemset in L)
            {
                AddResultLine(itemset.ToString());
            }
            AddResultLine(string.Empty);

            //do mining
            List<AssociationRule> allRules = Mining.Mine(_db, L, ConfidenceThreshold);
            AddResultLine(allRules.Count + " Association Rules");
            foreach (AssociationRule rule in allRules)
            {
                AddResultLine(rule.ToString());
            }
            #endregion
        }
    }
}
